// 
// File:   add_matrix.h
// Author: cionescu
//
// Created on February 5, 2007, 2:01 PM
//

#ifndef _add_matrix_H
#define	_add_matrix_H
#include "dd/dd_matrix.h"
#include "dd/dd_basics.h"
#include "add_variables.h"
#include "add_vector.h"

#define ELEMENT_TYPE double

// TODO consistency verifications e.g. same columns and rows, same manager etc
class add_matrix {
    DdManager *manager;
    DdNode *matrix;
    DdNode **rvars;
    int num_rvars;
    DdNode **cvars;
    int num_cvars;
    
    public:
    add_matrix(DdManager *_manager, DdNode** _rvars, int _num_rvars, DdNode** _cvars, int _num_cvars)
    : manager(_manager), rvars(_rvars), cvars(_cvars), num_rvars(_num_rvars), num_cvars(_num_cvars){
      matrix = DD_Constant(_manager, 0);
    } 
    
    add_matrix(DdManager *_m, add_variables& rows, add_variables& cols) 
    : manager(_m){
      rvars=rows.get_raw_vector();
      num_rvars=rows.get_encoding_size();
      cvars=cols.get_raw_vector();
      num_cvars=cols.get_encoding_size();
      matrix = DD_Constant(_m, 0);
    }
    
    // Setting an element in the matrix
    void
    set_element(int rindex, int cindex, ELEMENT_TYPE value) {
      matrix = DD_SetMatrixElement(manager, matrix, rvars, num_rvars, cvars, num_cvars, rindex, cindex, value);
    }
    
    DdNode*
    get_add() {
      return matrix;
    }
    
    DdNode*
    matrix_multiply(add_matrix const& _matrix) {
      return DD_MatrixMultiply(manager, matrix, _matrix.matrix, rvars, num_rvars, MM_BOULDER);
    }
    
    void
    matrix_transpose() {
      matrix = DD_Transpose(manager, matrix, rvars, cvars, num_rvars);
    }
    
    void
    identity(){
      matrix = DD_Identity(manager, rvars, cvars, num_rvars);
    }
    
    void
    print() {
      DD_PrintInfo(manager, matrix, num_rvars+num_cvars);
      DD_PrintMatrix(manager, matrix, rvars, num_rvars, cvars, num_cvars);
    }
};

#endif	/* _add_matrix_H */
